package service

import (
	"fmt"
	jsoniter "github.com/json-iterator/go"
	"github.com/lib/pq"
	"gpt-api/framework/cache"
	"gpt-api/framework/codes"
	"gpt-api/framework/db"
	"gpt-api/pkg/design"
	"gpt-api/pkg/model"
	"gpt-api/pkg/response"
	"time"
)

type FeedbackImpl struct {
	db    *db.DB
	cache *cache.RedisClient
}

func NewFeedbackImpl() *FeedbackImpl {
	connSingleInstance := design.GetSingleInstance()

	return &FeedbackImpl{
		db:    connSingleInstance.GetDB(),
		cache: connSingleInstance.GetCache(),
	}
}

type CategoryResp struct {
	Id      uint   `json:"id"`
	Content string `json:"content"`
	Default bool   `json:"default"`
}

func (f *FeedbackImpl) ProjectCategory(project string) (err error, resp []*model.QuestionCategory) {
	redisKey := fmt.Sprintf("project_%s_feedback_category", project)
	if f.cache.Exists(redisKey).Val() == 0 {
		err = f.db.Where("project = ?", project).Order("sort asc").Find(&resp).Error
		if err != nil {
			return
		}

		str, _ := jsoniter.Marshal(resp)
		f.cache.Set(redisKey, string(str), time.Minute*10)
		return
	} else {
		val := f.cache.Get(redisKey).Val()
		err = jsoniter.UnmarshalFromString(val, &resp)
	}

	return
}

// GetTransDataFromKeys 获取翻译
func GetTransDataFromKeys(lang string, keys ...string) (data []string, err error) {
	_, ok := codes.StatusText[lang]
	if !ok {
		return keys, nil
	}

	translationMap := codes.StatusText[lang]
	for _, key := range keys {
		if _, exist := translationMap[key]; exist {
			data = append(data, translationMap[key])
		} else {
			data = append(data, key)
		}
	}

	return
}

// ListCategory 获取反馈类别
func (f *FeedbackImpl) ListCategory(lang, project string) (resp []CategoryResp, err error) {
	var cates []*model.QuestionCategory

	err, cates = f.ProjectCategory(project)
	if err != nil {
		return
	}

	for i := range cates {
		c := CategoryResp{}
		c.Id = cates[i].ID
		var data []string
		data, err = GetTransDataFromKeys(lang, cates[i].TranslateKey)
		if err != nil {
			return
		}
		c.Content = data[0]
		// default set other
		if cates[i].Default == 1 {
			c.Default = true
		}
		resp = append(resp, c)
	}
	return
}

// Submit 上传问题
func (f *FeedbackImpl) Submit(req response.SubmitReq, platform, version, deviceModel string) (err error) {
	ques := model.Question{
		Project:     req.Project,
		CategoryId:  req.CategoryID,
		Description: req.Description,
		Images:      pq.StringArray(req.Images),
		Email:       req.Email,
		Platform:    platform,
		Version:     version,
		Product:     deviceModel,
	}
	if err = f.db.Create(&ques).Error; err != nil {
		return
	}
	return
}

type Question struct {
	model.Question
	CategoryName  string    `json:"category_name"`
	OmitID        *struct{} `json:"ID,omitempty" gorm:"-"`
	Id            int       `json:"id"`
	OmitCreatedAt *struct{} `json:"CreatedAt,omitempty" gorm:"-"`
	UpdatedAt     *struct{} `json:",omitempty" gorm:"-"`
	DeletedAt     *struct{} `json:",omitempty" gorm:"-"`
	CreatedTime   int64     `json:"created_time"`
}

type QuestionResp struct {
	List  []Question `json:"list"`
	Total int        `json:"total"`
}

// ListQues 问题列表
func (f *FeedbackImpl) ListQues(project *string, category_id, status, page, size *int, lang string) (resp QuestionResp, err error) {
	tx := f.db.Model(new(model.Question)).
		Joins("join question_category qc on question.category_id = qc.id").
		Where("question.project = ?", project)
	if category_id != nil {
		tx = tx.Where("category_id = ?", category_id)
	}
	if status != nil {
		tx = tx.Where("status = ?", status)
	}
	if page == nil {
		page = new(int)
		*page = 1
	}
	if size == nil {
		size = new(int)
		*size = 10
	}
	var questionList []Question
	tx = tx.Select("question.*, qc.translate_key as category_name").Order("question.id desc")
	resp.Total, err = db.FindPage(tx, *page, *size, &questionList)
	if err != nil {
		return
	}
	if resp.Total == 0 {
		resp.List = make([]Question, 0)
		return
	}
	for i := range questionList {
		questionList[i].CreatedTime = questionList[i].CreatedAt.Unix()
		var data []string
		data, err = GetTransDataFromKeys(lang, questionList[i].CategoryName)
		if err != nil {
			return
		}
		questionList[i].CategoryName = data[0]
		if questionList[i].Images == nil {
			sa := pq.StringArray(make([]string, 0))
			questionList[i].Images = sa
		}
	}
	resp.List = questionList
	return
}

// QuesManage 问题处理改变状态
func (f *FeedbackImpl) QuesManage(id, status int) (err error) {
	var ques model.Question
	if err = f.db.Where("id = ?", id).Find(&ques).Error; err != nil {
		return
	}
	if ques.ID != uint(id) {
		err = fmt.Errorf("question %d not exist", id)
		return
	}
	d := map[string]interface{}{
		"status": status,
	}
	if err = f.db.Model(&model.Question{}).Where("id = ?", id).UpdateColumns(d).Error; err != nil {
		return
	}
	return
}
